<html>
<head><meta charset="utf-8"><title>transmute of structs containing  DST · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html">transmute of structs containing  DST</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="223778374"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/transmute%20of%20structs%20containing%20%20DST/near/223778374" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mahmoud Al-Qudsi <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html#223778374">(Jan 23 2021 at 21:43)</a>:</h4>
<p>Is the behavior of transmute when it comes to structs containing DSTs documented somewhere? Because I find the current behavior rather unintuitive, as demonstrated in this playground: <a href="https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=17c9086a8ec0cac77fcedc5cee57f108">https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=17c9086a8ec0cac77fcedc5cee57f108</a></p>



<a name="223782372"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/transmute%20of%20structs%20containing%20%20DST/near/223782372" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html#223782372">(Jan 23 2021 at 22:49)</a>:</h4>
<p>What happens here is that both <code>array</code> and <code>bytes</code> share the same metadata (slice length in this case) but for <code>array</code> there is an extra field that needs to be added to get the length of the pointed to object.</p>



<a name="223784994"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/transmute%20of%20structs%20containing%20%20DST/near/223784994" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mahmoud Al-Qudsi <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html#223784994">(Jan 23 2021 at 23:49)</a>:</h4>
<p>That's what I assumed, but my question is if it even makes sense for the result of transmute to differ from the original in size. Shouldn't the size of the non-dst fields in the array be subtracted from the reserved space rather than added to it?</p>



<a name="223799737"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/transmute%20of%20structs%20containing%20%20DST/near/223799737" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html#223799737">(Jan 24 2021 at 06:44)</a>:</h4>
<p>No, the metadata is just for the slice. If you were to use a trait object in both cases it wouldn't even be possible to change the size as you can't create a new vtable with a smaller size field.</p>



<a name="223824774"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/transmute%20of%20structs%20containing%20%20DST/near/223824774" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html#223824774">(Jan 24 2021 at 17:26)</a>:</h4>
<p>Btw, you should try to add a <code>#[repr(C)]</code> annotation on your type: while a DST field technically has to be the trailing field, so in your case there is no issue in that regard, it will help if you make the type of that trailing field be generic. This is very useful to create stack-allocated defs:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[derive(Debug)]</span><span class="w"></span>
<span class="cp">#[repr(C)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">DstArray</span><span class="o">&lt;</span><span class="n">Data</span><span class="w"> </span>: <span class="o">?</span><span class="nb">Sized</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">]</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">len</span>: <span class="kt">u8</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">data</span>: <span class="nc">Data</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">N</span>: <span class="kt">usize</span><span class="o">&gt;</span><span class="w"> </span><span class="nb">From</span><span class="o">&lt;</span><span class="p">[</span><span class="kt">u8</span><span class="p">;</span><span class="w"> </span><span class="n">N</span><span class="p">]</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">DstArray</span><span class="o">&lt;</span><span class="p">[</span><span class="kt">u8</span><span class="p">;</span><span class="w"> </span><span class="n">N</span><span class="p">]</span><span class="o">&gt;</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Hack to circumvent the lack of `&lt;const N: u8&gt; … [_; N as usize]`</span>
<span class="w">    </span><span class="n">__</span><span class="o">&lt;</span><span class="n">N</span><span class="o">&gt;</span><span class="w"> </span>: <span class="nc">FitsInto</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">from</span><span class="w"> </span><span class="p">(</span><span class="n">data</span>: <span class="p">[</span><span class="kt">u8</span><span class="p">;</span><span class="w"> </span><span class="n">N</span><span class="p">])</span><span class="w"></span>
<span class="w">      </span>-&gt; <span class="nc">Self</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">len</span>: <span class="nc">N</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>So that, someone outside the module can write:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">arr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DstArray</span>::<span class="n">from</span><span class="p">([</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">27</span><span class="p">]);</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">dst_arr</span>: <span class="kp">&amp;</span><span class="nc">DstArray</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">arr</span><span class="p">;</span><span class="w"></span>
</code></pre></div>
<ul>
<li><a href="https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=0ded1866511e8fa4a7fde37464e2d1a3">Playground</a></li>
</ul>
<hr>
<p>Finally, rather than transmuting pointers to DSTs, whose layout is not guaranteed, you should try to favor <code>as</code> casts:</p>
<div class="codehilite" data-code-language="Diff"><pre><span></span><code>    pub
    unsafe
    fn from_ptr (ptr: *const u8)
      -&gt; &amp;'static DstArray
    {
        let len = *ptr as usize;
        // len may be zero, but we always have the length field itself
<span class="gd">-       let bytes: &amp;'_ [u8] = ::core::slice::from_raw_parts(ptr, len as usize + 1);</span>
<span class="gd">-       let array: &amp;'static DstArray = ::core::mem::transmute(bytes);</span>
<span class="gi">+       let bytes: *const [u8] = ::core::ptr::slice_from_raw_parts(ptr, len as usize);</span>
<span class="gi">+       let array: &amp;'_ DstArray = &amp;*(bytes as *const DstArray);</span>
</code></pre></div>
<ul>
<li>(Regarding that cast, the idea is that <code>PtrTo&lt; [DstArray&lt;u8&gt;] &gt;</code> can be casted back and forth to/from <code>PtrTo&lt; DstArray&lt;[u8]&gt; &gt;</code> (and in that snippet I am abusing that <code>PtrTo&lt; [DstArray&lt;u8&gt;] &gt;</code> is the same as <code>PtrTo&lt; [u8] &gt;</code>), preserving the <code>ptr</code> and <code>len</code> fields. It's hacky, but it's the most guaranteed thing so far).</li>
</ul>
<p>And by doing it that way, we do notice that you were off by one in the length field of that fat pointer.</p>



<a name="223846616"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/transmute%20of%20structs%20containing%20%20DST/near/223846616" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mahmoud Al-Qudsi <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/transmute.20of.20structs.20containing.20.20DST.html#223846616">(Jan 25 2021 at 01:07)</a>:</h4>
<p><span class="user-mention" data-user-id="232018">@Daniel Henry-Mantilla</span> thanks for the detailed reply - especially for including that <code>FitsInto&lt;&gt;</code> magic, which I can find much use for (I was previously calling a const function and using <code>const_panic</code> to include an assert in there based off the length of the <code>const N: usize</code> parameter).</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>